package com.anli.xianliu;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletResponse;
import java.util.Collections;

/**
 * @author: LI-CI-GAO
 * 作者: licigao
 * 日期: 2021/8/30  9:52
 * 描述:
 */
@Aspect
@Component
public class TestXialLiuAop {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Pointcut("execution(public * com.anli.web.*.*(..))")
    public void pointcut(){}


    @Around("pointcut() && @annotation(com.anli.xianliu.XianLiuAnn)")
    public Object processHandler(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();

        XianLiuAnn annotation = signature.getMethod().getAnnotation(XianLiuAnn.class);

        String limitKey = annotation.key();

        String limitRate = annotation.limitRate();

        String expireKey = annotation.expireKey();

        //String lur="if redis.call('incr',KEYS[1]) <= tonumber(ARGV[1]) then if redis.call('get',KEYS[1]) == '1' then redis.call('expire',KEYS[1],100) end return 1 else return 0 end";
        //String lur="if redis.call('incr',KEYS[1])<=tonumber("+limitRate+") then if redis.call('get',KEYS[1]) == '1' then redis.call('expire',KEYS[1],tonumber("+expireKey+")) end return 1 else return 0 end";

        StringBuilder stringBuffer=new StringBuilder("if redis.call('incr',KEYS[1])<=tonumber(");
        stringBuffer.append(limitRate);
        stringBuffer.append(") then if redis.call('get',KEYS[1]) == '1' then redis.call('expire',KEYS[1],tonumber(");
        stringBuffer.append(expireKey);
        stringBuffer.append(")) end return 1 else return 0 end");

        String lur=stringBuffer.toString();

        DefaultRedisScript<Long> redisScript=new DefaultRedisScript<>();
        redisScript.setScriptText(lur);
        redisScript.setResultType(Long.class);

        Long execute = redisTemplate.execute(redisScript, Collections.singletonList(limitKey));

        if(execute==1){
           return proceedingJoinPoint.proceed();
        }else{
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletResponse response = requestAttributes.getResponse();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().print("超过负载限制，开始限流");
            return null;
        }
    }
}
